import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Polygon;
import java.util.ArrayList;

import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSlider;
import javax.swing.JTextArea;
import javax.swing.SwingConstants;
import javax.swing.WindowConstants;

public class Region extends MapObject
{
    private static final long serialVersionUID = -8312130595369431607L;

    private ArrayList<Double> horizontalOffsets = new ArrayList<Double>();
    private ArrayList<Double> verticalOffsets = new ArrayList<Double>();

    public Region(Map map, MapPanel containingPanel)
    {
	super(map, containingPanel);
	this.icon = new Polygon();
	this.color = Color.BLUE;
	this.transperancy = 128;
    }

    // copy constructor
    @SuppressWarnings("unchecked")
    public Region(Region region)
    {
	super(region);

	// This should be sufficient, as you cannot move a region once it has been created.
	// If moving a region is implemented, then a deep copy will need to be used
	this.horizontalOffsets = (ArrayList<Double>) region.horizontalOffsets.clone();
	this.verticalOffsets = (ArrayList<Double>) region.verticalOffsets.clone();
    }

    @Override
    public void paint(Graphics g)
    {
	super.paint(g);
	((Polygon) this.icon).invalidate();
    }

    public void addPoint(int x, int y)
    {
	((Polygon) this.icon).addPoint(x, y);
	this.horizontalOffsets.add((x - this.map.getStartXCoord()) / this.map.getZoomLevel());
	this.verticalOffsets.add((y - this.map.getStartYCoord()) / this.map.getZoomLevel());
    }

    @Override
    public void setLoc(int x, int y)
    {
	this.xCoord = x;
	this.yCoord = y;
	this.addPoint(x, y);
    }

    @Override
    public void displayCreatePrompt(boolean isEditing)
    {
	JDialog creationWindow = new JDialog((JDialog)null, "Enter " + this.getClass().getName() + " Information", true);
	creationWindow.setResizable(false);

	JPanel contentPanel = new JPanel();

	contentPanel.setPreferredSize(new Dimension(400, 300));

	contentPanel.setLayout(new GridBagLayout());
	GridBagConstraints constraints = new GridBagConstraints();
	constraints.fill = GridBagConstraints.HORIZONTAL;

	JLabel nameLabel = new JLabel("name: ");
	JLabel infoLabel = new JLabel("Info: ");
	JLabel transparencyLabel = new JLabel("Transparency: ");

	JTextArea nameInfo = new JTextArea();
	nameInfo.setText(this.name);
	nameInfo.addFocusListener(new InstructorUI.ClearTextListener(nameInfo.getText()));
	JScrollPane nameScrollArea = new JScrollPane();
	nameScrollArea.getViewport().add(nameInfo);

	JButton objectInfo = new JButton("Edit Info");
	objectInfo.addActionListener(new ObjectInfoWindowListener());

	JButton colorChooser = new JButton("Color:");
	colorChooser.addActionListener(new ColorButtonListener());

	JSlider transparency = new JSlider(SwingConstants.HORIZONTAL, 0, 255, this.transperancy);
	transparency.addChangeListener(new SliderTransperancyListener());
	transparency.setMajorTickSpacing(transparency.getMaximum());
	transparency.setPaintLabels(true);

	JButton addLink = new JButton("Add Hyperlink");
	addLink.addActionListener(new AddHyperlinkWindowListener());

	JButton removeLink = new JButton("Remove Hyperlink");
	removeLink.addActionListener(new RemoveHyperlinkWindowListener());

	JButton save = new JButton("Save");
	save.addActionListener(new CreatePromptSaveListener(creationWindow, nameInfo));

	JButton delete = new JButton("Delete");
	delete.addActionListener(new DeleteObjectListener(creationWindow));

	// GridBagLayout code sucks
	constraints.weightx = .1;
	constraints.weighty = .25;
	constraints.gridx = 0;
	constraints.gridy = 0;
	constraints.ipady = 10;
	contentPanel.add(nameLabel, constraints);

	constraints.gridx = 1;
	constraints.gridy = 0;
	constraints.anchor = GridBagConstraints.LINE_START;
	contentPanel.add(nameScrollArea, constraints);

	constraints.gridx = 0;
	constraints.gridy = 1;
	contentPanel.add(infoLabel, constraints);

	constraints.gridx = 1;
	constraints.gridy = 1;
	constraints.ipady = 100;
	contentPanel.add(objectInfo, constraints);

	constraints.gridx = 1;
	constraints.gridy = 2;
	constraints.ipady = 10;
	contentPanel.add(colorChooser, constraints);

	constraints.gridx = 0;
	constraints.gridy = 3;
	contentPanel.add(transparencyLabel, constraints);

	constraints.gridx = 1;
	constraints.gridy = 3;
	contentPanel.add(transparency, constraints);

	constraints.gridx = 0;
	constraints.gridy = 4;
	contentPanel.add(addLink, constraints);

	constraints.gridx = 1;
	constraints.gridy = 4;
	contentPanel.add(removeLink, constraints);

	constraints.gridx = 0;
	constraints.gridy = 5;
	constraints.gridwidth = isEditing ? 1 : 2;
	constraints.anchor = GridBagConstraints.PAGE_END;
	contentPanel.add(save, constraints);
	creationWindow.add(contentPanel);

	if (isEditing)
	{
	    constraints.gridx = 1;
	    constraints.gridy = 5;
	    contentPanel.add(delete, constraints);
	    creationWindow.add(contentPanel);
	}

	creationWindow.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
	creationWindow.addWindowListener(new WindowCloseListerner());
	creationWindow.pack();
	
	save.requestFocusInWindow();
	// setting the relative location to null sets the location to the center of the screen
	creationWindow.setLocationRelativeTo(null);
	creationWindow.setVisible(true);
    }

    @Override
    public MapObject copy()
    {
	return new Region(this);
    }
    
    public int getNumPoints()
    {
	return ((Polygon) this.icon).npoints;
    }

    @Override
    public void scaleCoords()
    {
	for (int i = 0; i < ((Polygon) this.icon).npoints; i++)
	{
	    int tempX = (int) (this.map.getStartXCoord() + (this.horizontalOffsets.get(i) * this.map.getZoomLevel()));
	    int tempY = (int) (this.map.getStartYCoord() + (this.verticalOffsets.get(i) * this.map.getZoomLevel()));
	    ((Polygon) this.icon).xpoints[i] = tempX;
	    ((Polygon) this.icon).ypoints[i] = tempY;
	}
    }

    @SuppressWarnings("unchecked")
    public void copyTo(Region region)
    {
	super.copyTo(region);
	this.horizontalOffsets = (ArrayList<Double>) region.horizontalOffsets.clone();
	this.verticalOffsets = (ArrayList<Double>) region.verticalOffsets.clone();
    }
}
